'爬取的字段信息：导演，评分，标题，演员，封面，详情页链接，年份，电影类型，国家，语言，时间，片长，评论个数，星级，简介，评论，图片链接，预告片链接'

import csv
import os
import re
import pandas as pd
import requests
import random
import time
import json
from pymysql import *
from lxml import etree
from sqlalchemy import create_engine
from datetime import datetime, timedelta

engine = create_engine('mysql+pymysql://root:ws303630@localhost:3306/test')


class spider(object):
    """ 这段代码是一个类的初始化方法（__init__），用于设置类的初始属性。其中包含了一个名为`spiderUrl`的属性，以及一个名为`headers`的属性。`spiderUrl`是一个字符串，表示要爬取的网址，`headers`是一个字典，包含了请求头信息。在这段代码中，`headers`属性中的`User-Agent`和`Cookie`是请求头中的两个字段，用于模拟浏览器发送请求。`User-Agent`字段用于告诉服务器发送请求的浏览器信息，`Cookie`字段用于保存用户登录状态或其他需要传递的信息。请注意：这里给出的`Cookie`内容是一个示例，实际使用时需要根据你的具体情况进行修改和设置。如果你希望使用这个`headers`属性进行请求，可以在相应的请求代码中使用该`headers`作为参数传递给请求函数。另外，为了保护隐私和安全，建议不要在公开的场合直接暴露自己的真实`Cookie`信息。 """

    def __init__(self):
        self.spiderUrl = 'https://movie.douban.com/j/new_search_subjects?'
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0',
            'Cookie': 'll="118160"; bid=n7U3zmjfTuc; _pk_id.100001.4cf6=9b9860ce562eaa21.1684325777.; __yadk_uid=mDZKEvyucaB3aIAXY3UYJ20bY2u4VmmT; __gads=ID=0360a756bb0824f1-22ff9cead3e0003c:T=1684325778:RT=1684325778:S=ALNI_MYt2YKDj9L2UsC77oMdsi0_92YoaQ; __gpi=UID=00000c0759bfdce3:T=1684325778:RT=1684325778:S=ALNI_MaRLmviQevXBNc1_NcF7mMgqFNPmQ; _vwo_uuid_v2=D82E2781BA7514D9BEFB0A88699D5812E|cabb83a8f1479a783ff34d84235bf4eb; ct=y; ap_v=0,6.0; _pk_ref.100001.4cf6=%5B%22%22%2C%22%22%2C1704694064%2C%22https%3A%2F%2Fcn.bing.com%2F%22%5D; _pk_ses.100001.4cf6=1; __utma=30149280.940552568.1684325777.1704649762.1704694064.13; __utmb=30149280.0.10.1704694064; __utmc=30149280; __utmz=30149280.1704694064.13.7.utmcsr=cn.bing.com|utmccn=(referral)|utmcmd=referral|utmcct=/; __utma=223695111.79828918.1684325777.1704649762.1704694064.13; __utmb=223695111.0.10.1704694064; __utmc=223695111; __utmz=223695111.1704694064.13.7.utmcsr=cn.bing.com|utmccn=(referral)|utmcmd=referral|utmcct=/'
        }
        # self.page = 0  #因为程序一旦中断，代码只会从零页重新爬取，不能继续之前的页数爬取，所以不用这个方法，删掉他


    def init(self):
        if not os.path.exists('movies.csv'):
            with open('movies.csv', 'w', newline='') as writer_f:
                writer = csv.writer(writer_f)
                writer.writerow(
                    ['directors', 'rate', 'title', 'casts', 'cover', 'detailLink', 'year', 'types', 'country', 'lang',
                     'time', 'movieTime', 'comment_len', 'starts', 'summary', 'comments', 'imgList', 'movieUrl'])
        if not os.path.exists('./spiderPage.txt'):
            with open('./spiderPage.txt', 'w', encoding='utf-8') as f:
                f.write('0\n')

        try:
            conn = connect(host='localhost', user='root', password='ws303630', database='doubanmovie', port=3306, charset='utf8mb4')
            sql = '''
                    create table movies(
                        id int primary key auto_increment,
                        directors varchar(255),
                        rate varchar(255),
                        title varchar(255),
                        casts varchar(255),
                        cover varchar(255),
                        detailLink varchar(255),
                        year varchar(255),
                        types varchar(255),
                        country varchar(255),
                        lang varchar(255),
                        time varchar(255),
                        movieTime varchar(255),
                        comment_len varchar(255),
                        starts varchar(255),
                        summary varchar(2555),
                        comments text,
                        imgList varchar(2555),
                        movieUrl varchar(255)
                    )
                '''
            cursor = conn.cursor()
            cursor.execute(sql)
            conn.commit()
        except:
            pass

    '''这段代码是一个类中的方法，名为`get_page`。它的作用是从一个名为`spiderPage.txt`的文件中读取最后一行，并返回去除了首尾空白字符的结果。代码中使用了`open`函数来打开`spiderPage.txt`文件，`'r'`参数表示以只读模式打开文件。然后使用`with`语句来确保文件在使用完毕后自动关闭。`readlines()`方法用于读取文件的所有行，并以列表形式返回。通过索引`[-1]`可以获取列表中的最后一行。最后使用`strip()`方法去除字符串首尾的空白字符。需要注意的是，文件路径`'./spiderPage.txt'`表示该文件位于当前工作目录下。如果文件不在同一目录下，需要提供正确的文件路径。这段代码适用于读取文件中的最后一行，可能用于某种爬虫程序中的页面处理。'''

    def get_page(self):
        with open('./spiderPage.txt', 'r') as r_f:
            # print(r_f.readlines())
            return r_f.readlines()[-1].strip()

    ''' 这段代码是一个类中的方法，名为set_page。它的功能是将传入的newPage参数写入到名为spiderPage.txt的文件中。这个方法使用了with open语句来打开spiderPage.txt文件，并以追加模式打开文件。然后，使用write方法将newPage参数转换为字符串，并写入文件中。最后，通过添加换行符\n来确保每个写入的内容都占据一行。'''

    def set_page(self, newPage):
        with open('./spiderPage.txt', 'a') as w_f:
            w_f.write(str(newPage) + '\n')  # 整形转换为字符串

    """ """

    def spiderMain(self):
        '''这段代码是一个名为`spiderMain`的方法，它是一个类中的方法。该方法首先调用了`get_page`方法，将返回的最后一行数据赋值给变量`page`。然后使用这个`page`变量作为参数，构建了一个名为`params`的字典，其中`start`键的值是`page`乘以20。接下来，打印了一个正在爬取的提示信息，其中页数是`page`加1。然后，使用`requests`库发送了一个GET请求，请求的URL是`spiderUrl`，请求头是`headers`，请求参数是`params`。返回的响应是JSON格式的数据，将其赋值给了`respJson`变量。接下来，从`respJson`中取出了`data`键对应的值，赋值给了`respJson`变量。最后，创建了一个空列表`resultList`。'''
        page = self.get_page()  # 优化外加
        params = {
            # 'start':self.page *20     #原始
            'start': int(page) * 20  # 优化
        }

        # print('正在爬取第{}页'.format(self.page))   #原始
        # print('正在爬取第{}页'.format(page))     #优化
        print('正在爬取第{}页'.format(int(page) + 1))  # 从第一页开始
        # print(requests.get(self.spiderUrl, headers=self.headers, params=params).text)
        respJson = requests.get(self.spiderUrl, headers=self.headers, params=params).json()  # verify=False
        # content = respJson.content.decode()
        # print(content)
        # print(respJson)
        # urllib3.disable_warnings()
        respJson = respJson['data']
        resultList = []  # 最后优化修改

        '''以下代码是一个用于爬取电影数据的方法。它首先通过传入的`respJson`参数获取到电影信息的JSON数据，并使用`enumerate`函数遍历每个电影的信息。然后，它从每个电影的信息中提取出需要的数据，并存储在`resultData`列表中。

        具体来说，它提取了以下数据：

        1. 电影导演：将导演的姓名使用逗号连接起来。
        2. 电影评分：提取电影的评分。
        3. 电影名字：提取电影的名称。
        4. 电影演员：将演员的姓名使用逗号连接起来。
        5. 电影封面：提取电影的封面图片链接。
        6. 电影详情链接：提取电影的详情链接。
        7. 电影年份：从详情页面中提取电影的年份。
        8. 电影类型：从详情页面中提取电影的类型，并将其使用逗号连接起来。
        9. 电影制片国家：从详情页面中提取电影的制片国家。
        10. 语言：从详情页面中提取电影的语言。
        11. 上映时间：从详情页面中提取电影的上映时间。
        12. 电影片长：从详情页面中提取电影的片长。
        13. 短评个数：从详情页面中提取电影的短评个数。
        14. 电影星级占比：从详情页面中提取电影的星级占比。
        15. 电影简介：从详情页面中提取电影的简介。
        16. 电影短评：从详情页面中提取电影的短评，并将其以JSON格式存储。
        17. 图片列表：从详情页面中提取电影的图片链接，并将其使用逗号连接起来。
        18. 电影预告片链接：从详情页面中提取电影的预告片链接。

        最后，它将每个电影的提取结果存储在`resultList`列表中，并返回该列表。

        值得注意的是，代码中使用了异常处理来避免可能的错误，但是对错误的处理方式是直接忽略，没有给出具体的处理逻辑。这可能会导致一些潜在的问题。另外，代码中还存在一些随机生成数据的逻辑，用于处理一些缺失或不规范的数据。'''
        for index, movieData in enumerate(respJson):
            try:

                # print(movieData)
                # print('正在爬取第%d条' % index)     #从第零条开始
                print('正在爬取第%d条' % (index + 1))  # 从第一条开始
                resultData = []

                '''这段代码用于将电影导演的信息以逗号分隔的形式添加到一个列表中。具体解释如下：
                - `movieData`是一个字典，包含了电影的各种信息，其中`directors`是一个列表，包含了电影的导演信息。
                - `','.join(movieData['directors'])`的作用是将`directors`列表中的元素以逗号分隔的形式连接成一个字符串。
                - `resultData.append()`是将上述连接后的字符串添加到名为`resultData`的列表中。

                这段代码的作用是将每个电影的导演信息添加到`resultData`列表中，以便后续使用。'''
                # 电影导演(directors )
                resultData.append(','.join(movieData['directors']))

                """这段代码用于将电影的评分信息添加到一个列表中。具体解释如下：

                - `movieData`是一个字典，包含了电影的各种信息，其中`rate`是电影的评分。
                - `resultData.append(movieData['rate'])`的作用是将`rate`的值添加到名为`resultData`的列表中。

                这段代码的作用是将每个电影的评分信息添加到`resultData`列表中，以便后续使用。"""
                # 电影评分(rate )
                resultData.append(movieData['rate'])

                # 电影名字(title)
                resultData.append(movieData['title'])

                # 电影演员(casts )
                resultData.append(','.join(movieData['casts']))

                # 电影封面(cover)
                resultData.append(movieData['cover'])

                # 电影详情链接(detaillink)
                resultData.append(movieData['url'])
                # print(resultData)

                '''这段代码用于发送HTTP请求获取电影详情页面的HTML内容，并使用XPath来解析HTML页面。具体解释如下：
                - `requests.get(movieData['url'], headers=self.headers)`是使用`requests`库发送GET请求，从`movieData`字典中获取电影详情页面的URL，并添加了自定义的请求头`self.headers`。这可以用于模拟浏览器发送请求，以避免网站的反爬机制。
                - `respDetailHTML`是获取到的响应对象，可以通过`respDetailHTML.text`获取到HTML内容。
                - `etree.HTML(respDetailHTML.text)`使用`etree`模块的`HTML`方法将HTML内容转换为可操作的XPath对象，方便后续的页面解析操作。
                这段代码的作用是发送HTTP请求获取电影详情页面的HTML内容，并将其转换为可操作的XPath对象，以方便后续的页面解析操作。'''
                respDetailHTML = requests.get(movieData['url'], headers=self.headers)
                # print(respDetailHTML.status_code)
                respDetailHTMLXpath = etree.HTML(respDetailHTML.text)

                '''这段代码使用了正则表达式来从HTML页面中提取电影的年份信息。它首先使用XPath来定位到包含年份信息的HTML元素，然后使用正则表达式`\d+`来匹配其中的数字部分。最后，它将提取到的年份信息添加到`resultData`列表中。

                这里有一些需要注意的地方：
                - 这段代码使用了`re.search()`函数来搜索匹配正则表达式的第一个结果，并使用`.group()`方法来获取匹配到的结果。
                - 代码中使用了XPath来定位到HTML元素。XPath是一种用于在XML和HTML文档中定位节点的语言。
                - 代码中使用了`respDetailHTMLXpath`来表示经过XPath解析后的HTML页面。'''
                # 电影年份(year)  //*[@id="content"]/h1/span[2]
                year = re.search('\d+',
                                 respDetailHTMLXpath.xpath('//*[@id="content"]//span[@class="year"]/text()')[0]).group()
                # print(respDetailHTMLXpath.xpath('//*[@id="content"]/h1/span[2]/text()')[0])
                resultData.append(year)

                '''这段代码用于从HTML页面中提取电影的类型信息。它使用XPath表达式定位到包含类型信息的HTML元素，并将每个类型添加到名为`types`的列表中。最后，它使用`','.join(types)`将列表中的类型信息连接成一个字符串，并将结果添加到`resultData`列表中。

                这里有一些需要注意的地方：
                - 代码中使用了`respDetailHTMLXpath`来表示经过XPath解析后的HTML页面。这个变量可能是之前的代码中定义的一个对象。
                - `//div[@id="info"]/span[@property="v:genre"]`是XPath表达式，它用于定位到含有电影类型信息的HTML元素。其中`div[@id="info"]`表示定位到id属性为"info"的div元素，`span[@property="v:genre"]`表示定位到property属性为"v:genre"的span元素。
                - `i.text`用于获取匹配到的HTML元素的文本内容，并将其添加到`types`列表中。'''
                # 电影类型  //*[@id="info"]/span[5]
                types = []
                for i in respDetailHTMLXpath.xpath('//div[@id="info"]/span[@property="v:genre"]'):
                    types.append(i.text)
                resultData.append(','.join(types))

                '''这段代码是用来解析HTML页面并提取电影信息的。首先，通过XPath表达式 `//div[@id="info"]/text()` 从页面中获取到包含电影信息的文本列表 `textInfo`。然后，使用一个循环遍历 `textInfo` 中的每个元素，并进行以下操作：

                1. 使用 `strip()` 方法去除首尾空白字符。
                2. 使用条件判断语句 `if i.strip() and not i.strip() == '/'` 来过滤掉只包含斜杠字符的元素。
                3. 将符合条件的元素添加到列表 `texts` 中。
                最后，使用 `','.join(texts[0].split(sep='/'))` 将列表 `texts` 的第一个元素按斜杠字符分割，并用逗号连接起来。然后将结果添加到名为 `resultData` 的列表中。                
                这段代码的作用是将电影信息整理成一个字符串，并将其添加到 `resultData` 列表中。'''
                # 电影制片国家
                textInfo = respDetailHTMLXpath.xpath(' //div[@id="info"]/text()')
                # print(textInfo)
                texts = []
                for i in textInfo:
                    if i.strip() and not i.strip() == '/':
                        texts.append(i)
                # print(texts)
                resultData.append(','.join(texts[0].split(sep='/')))

                # 语言(lang)
                resultData.append(','.join(texts[1].split(sep='/')))

                '''这段代码是用来从HTML页面中提取电影的初始发布日期，并将其添加到 `resultData` 列表中。首先，使用XPath表达式 `//*[@id="info"]/span[@property="v:initialReleaseDate"]/@content` 从页面中获取到包含初始发布日期的属性值列表.
                然后，通过索引 `[0]` 获取到列表中的第一个属性值，并使用切片 `[:10]` 取该属性值的前10个字符，即日期部分。最后，使用 `append()` 方法将提取到的日期添加到名为 `resultData` 的列表中。
                这段代码的作用是将电影的初始发布日期提取出来，并添加到 `resultData` 列表中。'''
                # 上映时间(time)
                # print(respDetailHTMLXpath.xpath('//*[@id="info"]/span[@property="v:initialReleaseDate"]/@content')[0][:10])
                resultData.append(
                    respDetailHTMLXpath.xpath('//*[@id="info"]/span[@property="v:initialReleaseDate"]/@content')[0][
                    :10])

                '''这段代码是用于解析JSON数据和HTML页面来提取电影信息，并将其存储在一个名为resultData的列表中。代码中使用了XPath解析和正则表达式来获取电影时长信息。

                首先，代码尝试使用XPath语法来获取电影时长信息。如果成功找到时长信息，则将其添加到resultData列表中。

                如果无法通过XPath找到时长信息，代码会尝试使用正则表达式来从texts列表中的第五个元素中提取数字部分作为时长信息。如果成功提取到时长信息，则将其添加到resultData列表中。

                如果以上两种方法都无法获取到时长信息，则代码会随机生成一个31到59之间的整数作为时长信息，并将其添加到resultData列表中。'''
                # 电影片长(movieTime)  //*[@id="info"]/span[13]
                try:
                    # print(respDetailHTMLXpath.xpath('//*[@id="info"]/span[@property="v:runtime"]/@content')[0])
                    resultData.append(
                        respDetailHTMLXpath.xpath('//*[@id="info"]/span[@property="v:runtime"]/@content')[0])
                except:
                    # print(texts)   #有的是电视剧，没有电影时长，所以try一下
                    try:
                        resultData.append(re.search('\d+', texts[4]).group())
                    except:
                        resultData.append(random.randint(31, 59))

                # 短评个数(conment_len)  //*[@id="comments-section"]/div[1]/h2/span/a
                # print(respDetailHTMLXpath.xpath('//*[@id="comments-section"]/div[1]/h2/span/a/text()'))
                resultData.append(re.search('\d+', respDetailHTMLXpath.xpath(
                    '//*[@id="comments-section"]/div[1]/h2/span/a/text()')[0]).group())

                '''这段代码从HTML页面中提取电影的评分信息，并将其存储在一个名为`starts`的列表中。然后，将`starts`列表中的元素以逗号分隔的形式添加到`resultData`列表中。

                这段代码使用了XPath解析HTML页面。首先，使用XPath表达式`//*[@id="interest_sectl"]/div[1]/div[3]/div[@class="item"]`选取了所有满足条件的元素。然后，使用`for`循环遍历这些元素，并从每个元素中提取评分信息。评分信息保存在`starts`列表中。最后，使用`','.join(starts)`将`starts`列表中的元素以逗号分隔的形式拼接成一个字符串，并将该字符串添加到`resultData`列表中。

                同时，这段代码还涉及到列表操作和字符串操作等基本知识点。'''
                # 电影星级占比(starts)     //*[@id="interest_sectl"]/div[1]/div[3]/div[1]
                starts = []
                # print(respDetailHTMLXpath.xpath('//*[@id="interest_sectl"]/div[1]/div[3]/div[@class="item"]'))
                for i in respDetailHTMLXpath.xpath('//*[@id="interest_sectl"]/div[1]/div[3]/div[@class="item"]'):
                    starts.append(i.xpath('./span[@class="rating_per"]/text()')[0])
                resultData.append(','.join(starts))

                ''' '''
                # 电影简介(summary)
                # print(respDetailHTMLXpath.xpath('//*[@id="link-report-intra"]/span/text()'))
                # resultData.append(respDetailHTMLXpath.xpath('//span[@property="v:summary"]/text()')[0].strip()) #博主的代码
                resultData.append(respDetailHTMLXpath.xpath('//*[@id="link-report-intra"]/span/text()')[0].strip())

                '''这段代码解析了一个HTML页面，并从中提取电影评论信息。代码首先定义了一个空列表`comments`用于存储评论信息。然后使用XPath解析器`respDetailHTMLXpath`选取了页面中`id`为"hot-comments"的`div`元素列表。接下来，通过循环遍历`commentsList`列表，对每个评论信息进行解析。

                在循环中，首先使用XPath表达式`.//h3/span[@class="comment-info"]/a/text()`提取评论用户的用户名，并将其存储在`user`变量中。接下来，使用正则表达式`re.search('\d+', i.xpath('.//h3/span[@class="comment-info"]/span[2]/@class')[0]).group()`从评论用户的星级评分中提取数字，并将结果存储在`start`变量中。如果提取失败，则使用`random.randint(1, 5) * 10`生成一个随机的星级评分。

                然后，尝试使用XPath表达式`.//h3/span[@class="comment-info"]/span[3]/@title`提取评论时间。如果提取失败，则生成一个随机的日期和时间，并将其格式化为`%Y-%m-%d %H:%M:%S`的字符串格式，存储在`times`变量中。

                最后，使用XPath表达式`.//p[@class="comment-content"]/span/text()`提取评论内容，并将其存储在`content`变量中。将`user`、`start`、`times`和`content`组合成一个字典，并将其转换为JSON格式的字符串，添加到`comments`列表中。

                最后，将`comments`列表中的所有评论信息转换为JSON格式的字符串，并将其添加到`resultData`列表中。

                总的来说，这段代码可以从HTML页面中提取电影评论信息，并将其存储在一个列表中。'''
                # 电影短评(comments)
                comments = []
                commentsList = respDetailHTMLXpath.xpath('//*[@id="hot-comments"]/div')
                for i in commentsList:
                    user = i.xpath('.//h3/span[@class="comment-info"]/a/text()')[0]
                    # start = i.xpath('.//h3/span[@class="comment-info"]/span[2]/@class')[0]
                    # print(start)
                    try:

                        start = re.search('\d+', i.xpath('.//h3/span[@class="comment-info"]/span[2]/@class')[0]).group()
                    except:
                        start = random.randint(1, 5) * 10
                    # print(start)
                    try:

                        times = i.xpath('.//h3/span[@class="comment-info"]/span[3]/@title')[0]
                    except:

                        # 生成随机的日期
                        start_date = datetime(2000, 1, 1)
                        end_date = datetime(2022, 12, 31)
                        random_date = start_date + timedelta(
                            seconds=random.randint(0, int((end_date - start_date).total_seconds())))

                        # 生成随机的时间
                        random_time = datetime.strptime(
                            f"{random.randint(0, 23)}:{random.randint(0, 59)}:{random.randint(0, 59)}", "%H:%M:%S")

                        # 输出结果
                        # print("随机日期:", random_date.strftime("%Y-%m-%d"))
                        # print("随机时间:", random_time.strftime("%H:%M:%S"))
                        times = random_date.strftime("%Y-%m-%d") + " " + random_time.strftime("%H:%M:%S")
                    # print(times)
                    content = i.xpath('.//p[@class=" comment-content"]/span/text()')[0]
                    comments.append({
                        'user': user,
                        'start': start,
                        'time': times,
                        'content': content
                    })
                resultData.append(json.dumps(comments))
                # print(resultData[-1])
                # print(user)
                # print(start)

                # 图片列表 (imgList)
                # imgList = respDetailHTMLXpath.xpath('//ul[@class="related-pic-bd  "]//img/@src')
                # print(respDetailHTMLXpath.xpath('//ul[@class="related-pic-bd  "]//img/@src'))
                resultData.append(','.join(respDetailHTMLXpath.xpath(
                    '//ul[contains(@class,"related-pic-bd  ")]//img/@src')))  # 有的爬取不到链接，改为包含这个标识的，并把=改为，（等于号改为逗号）
                # print(resultData[-1])

                '''这段代码是在解析HTML页面中提取电影预告片链接的部分。首先，使用XPath解析器从页面中提取电影预告片的URL，并将结果存储在`movieUrl`变量中。然后，使用`requests`库发送请求获取电影预告片的HTML页面，并使用XPath解析器解析该页面。最后，将解析得到的电影预告片链接存储在`resultData`列表中，并将`resultData`添加到`resultList`列表中。

                需要注意的是，代码使用了`try-except`语句来处理可能出现的异常情况。如果电影没有预告片，则会抛出异常，此时将0添加到`resultData`列表中。最后，将`resultData`添加到`resultList`列表中。

                这段代码涉及到XPath解析和列表操作等知识点，用于提取电影预告片链接并存储在列表中。'''
                # 电影预告片链接    class="label-trailer"
                try:
                    movieUrl = respDetailHTMLXpath.xpath(
                        '//ul[contains(@class,"related-pic-bd  ")]/li[@class="label-trailer"]/a/@href')[
                        0]  # =（等于）改为，（逗号）
                    # print(movieUrl)
                    movieHTML = requests.get(movieUrl, headers=self.headers)
                    movieHTMLXpath = etree.HTML(movieHTML.text)
                    # print(movieHTMLXpath.xpath('//video/source/@src')[0])
                    resultData.append(movieHTMLXpath.xpath('//video/source/@src')[0])
                    # resultData.append(respDetailHTMLXpath.xpath('//ul[@class="related-pic-bd  "]/li[@class="label-trailer"]/a/@href'))
                except:
                    resultData.append(0)  # 有的电影没有预告片，所以try了一下
                # print(resultData)

                resultList.append(resultData)  # 最后优化修改**********
                # print(resultList)
            except:
                pass

        '''将结果列表保存到CSV文件中，然后增加页面数，清空CSV文件，等待5秒后再次调用`spiderMain()`函数。对代码进行了一些优化修改。

        其中，`self.save_to_csv(resultList)`函数用于将结果列表保存到CSV文件中。`self.set_page(int(page) + 1)`函数用于增加页面数。`self.clear_csv()`函数用于清空CSV文件。`time.sleep(5)`函数用于等待5秒。最后，`self.spiderMain()`函数用于再次调用`spiderMain()`函数。'''

        try:
            print("正在保存到csv文件中:")
            self.save_to_csv(resultList)  # 最后优化修改**********
            print("保存到csv文件成功*******")
        except:
            print(("csv文件保存失败"))
        # self.page = self.page +1 #原始
        self.set_page(int(page) + 1)  # 优化,页数加1
        self.clear_csv()  # 简单清理数据
        time.sleep(5)
        self.spiderMain()  # 递归调用

    '''根据代码，`save_to_csv`函数接受一个结果列表作为参数，将其写入到CSV文件中。具体步骤如下：
    1. 使用`open`函数打开一个名为`tempData.csv`的文件，并以追加模式写入（`'a'`）。
    2. 创建一个`csv.writer`对象，将文件对象传递给它。
    3. 遍历结果列表`resultList`中的每一行数据`rowData`。
    4. 使用`writerow`方法将每一行数据写入CSV文件。
    5. 关闭文件。
    这样，结果列表中的数据就会被逐行写入到CSV文件中。'''

    def save_to_csv(self, resultList):
        with open('movies.csv', 'a', newline='', encoding='utf-8') as f:
            writer = csv.writer(f)
            for rowData in resultList:
                writer.writerow(rowData)

        # filename = './某条movies.csv'
        #
        # # 检查文件是否存在
        # file_exists = os.path.isfile(filename)
        #
        # with open(filename, 'w', newline='') as csvfile:
        #     csvwriter = csv.writer(csvfile)
        #
        #     # 如果文件不存在，写入列名
        #     if not file_exists:
        #         csvwriter.writerow(['directors', 'rate', 'title', 'casts', 'cover', 'detailLink','year', 'types', 'country', 'lang','time','movieTime', 'comment_len', 'starts', 'summary', 'comments', 'imgList', 'movieUrl'])
        #
        #     # 逐行写入数据
        #     for row in resultList:
        #         csvwriter.writerow(row)

        # with open('./某条_all_movies.csv', 'a', newline='', encoding='utf-8') as fr:
        #     writer = csv.writer(fr)
        #     for rowData in resultList:
        #         writer.writerow(rowData)

    '''这段代码是一个名为clear_csv的函数，它用于清理CSV文件中的数据。函数首先使用pd.read_csv函数读取CSV文件，并将其保存为一个DataFrame对象df。然后，函数使用df.dropna方法删除DataFrame中的缺失值。接下来，函数使用df.drop_duplicates方法删除DataFrame中的重复值。最后，函数调用self.save_to_sql方法将清理后的DataFrame保存到SQL数据库中。
    请注意，这段代码中的注释提到了另一种处理缺失值的方法df.fillna，但是该行代码被注释掉了。如果需要使用该方法，只需取消注释即可。
    此外，这段代码还调用了一个名为save_to_sql的方法，根据代码中的命名，它可能是用于将数据保存到SQL数据库的函数。'''

    def clear_csv(self):
        df = pd.read_csv('movies.csv')
        # df.dropna(inplace=True)  #删除缺失值
        '''前向填充（forward fill）是一种填充缺失值的方法，它将缺失值用它之前的非缺失值进行填充。具体来说，对于一个有缺失值的数据序列，前向填充会将缺失值用它之前的最近一个非缺失值进行填充。在 Pandas 中，可以使用 fillna() 函数的 method 参数来指定填充方法为前向填充，即 method='ffill'。示例代码如下：这样就会将 DataFrame 中的缺失值使用前向填充方法进行填充。前向填充方法在某些情况下非常有用，特别是当数据具有一定的趋势或序列性时，可以保留一部分数据的连续性。但需要注意的是，前向填充方法可能会在一些特定情况下引入一些偏差，因此在使用时需要根据具体情况进行判断和调整。'''
        # df.fillna(method='ffill', inplace=True)    #填充缺失值    两种都可以
        df.ffill(inplace=True)
        df.drop_duplicates()  # 删除重复值
        # print(df.shape)
        self.save_to_sql(df)
        # try:
        #     print("正在保存在数据库中:")
        #     self.save_to_sql(df)
        #     print("数据库保存成功*********")
        # except:
        #     print("保存失败")

    '''这段代码是一个名为save_to_sql的函数，用于将DataFrame保存到SQL数据库中。函数接受一个DataFrame对象df作为参数。首先，函数使用pd.read_csv函数读取CSV文件，但是在这段代码中没有将其赋值给任何变量，所以这行代码实际上是多余的。

    接下来，函数调用df.to_sql方法将DataFrame保存到SQL数据库中。该方法的参数包括要保存到的表名（这里是movies），数据库连接对象（con=engine），指定不保存索引值（index=False），以及对于已存在的表是否追加数据（if_exists='append'）。'''

    def save_to_sql(self, df):
        pd.read_csv('movies.csv')
        df.to_sql('movies', con=engine, index=False, if_exists='append')


if __name__ == '__main__':
    spiderObj = spider()
    spiderObj.init()
    # # spiderObj.get_page()
    spiderObj.spiderMain()
    # spiderObj.clear_csv()
